/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package bgu.sonar.util.ui.pans;

import bgu.sonar.util.async.Callback;
import bgu.sonar.util.async.FutureResult;
import bgu.sonar.util.async.TerminationCallback;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.ExecutorService;
import javax.swing.SwingUtilities;
import org.openide.util.Exceptions;

/**
 *
 * @author bennyl
 */
public abstract class DataViewSynchronizer<T> implements Callback<T> {

    private FutureResult<T> pendingResult = null;
    private boolean handlingSync = false;

    public abstract DataView<T> getDataView();

    public abstract FutureResult<T> fetchNewModel();

    public synchronized void sync(final ExecutorService pool) {
        if (handlingSync) {
            return;
        }
        handlingSync = true;

        getDataView().showLoading();
        if (pendingResult != null) {
            pendingResult.removeAllCallbacks();
            pendingResult.cancel();
            pendingResult.addCallback(new TerminationCallback() {
                @Override
                public void onTrminated(boolean success) {
                    synchronized (DataViewSynchronizer.this) {
                        handlingSync = false;
                        pendingResult = null;
                        sync(pool);
                    }
                }
            }, pool);
        } else {
            pendingResult = fetchNewModel();
            pendingResult.addCallback(this, pool);
            handlingSync = false;
        }
    }

    @Override
    public void onFailed(Exception ex, boolean interrupted) {
        getDataView().showError(ex);
    }

    @Override
    public void onSuccess(final T res) {
        try {
            SwingUtilities.invokeAndWait(new Runnable() {
                @Override
                public void run() {
                    getDataView().setModel(res);
                }
            });
        } catch (InterruptedException ex) { //dont care - someone canceled the sync..
        } catch (InvocationTargetException ex) {
            Exceptions.printStackTrace(ex);
        }
    }
}
